home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 September / macformat-041.iso / mac / Shareware City / Graphics / MacSPD / Sources / libply.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-22  |  40.0 KB  |  1,374 lines  |  [TEXT/MMCC]

  1. /*
  2.  * libply.c - a library of polygonized object output routines.
  3.  *
  4.  * Author:  Alexander Enzmann
  5.  *
  6.  * Modified: 1 November 1994
  7.  *           Alexander R. Enzmann
  8.  *           Changes necessary for transformations
  9.  *           Fixed vertex ordering in lib_output_cylcone
  10.  */
  11.  
  12.  
  13. /*-----------------------------------------------------------------*/
  14. /* include section */
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <math.h>
  19. #include <string.h>
  20. #include "lib.h"
  21. #include "drv.h"
  22.  
  23.  
  24. /*-----------------------------------------------------------------*/
  25. /* defines/constants section */
  26.  
  27. #define VERT(i, a) ((verts[gPoly_vbuffer[i]])[a])
  28.  
  29.  
  30. /*-----------------------------------------------------------------*/
  31. /* Polygon stack for making PLG files */
  32. object_ptr gPolygon_stack = NULL;
  33.  
  34. /* Keep track of how many vertices/faces have been emitted */
  35. unsigned long gVertex_count = 0; /* Vertex coordinates */
  36. unsigned long gNormal_count = 0; /* Vertex normals */
  37. unsigned long gFace_count = 0;
  38.  
  39. /* Storage for polygon indices */
  40. unsigned int *gPoly_vbuffer = NULL;
  41. int *gPoly_end = NULL;
  42.  
  43. /* Globals to determine which axes can be used to split the polygon */
  44. int gPoly_Axis1 = 0;
  45. int gPoly_Axis2 = 1;
  46.  
  47.  
  48. /*-----------------------------------------------------------------*/
  49. void
  50. lib_output_polygon_cylcone(base_pt, apex_pt)
  51.     COORD4 base_pt, apex_pt;
  52. {
  53.     double angle, delta_angle, divisor;
  54.     COORD3 axis, dir, norm_axis, start_norm;
  55.     COORD3 norm[4], vert[4], start_radius[4];
  56.     MATRIX nmx, mx;
  57.     int    i;
  58.  
  59.     SUB3_COORD3(axis, apex_pt, base_pt);
  60.     COPY_COORD3(norm_axis, axis);
  61.     lib_normalize_vector(norm_axis);
  62.  
  63.     SET_COORD3(dir, 0.0, 0.0, 1.0);
  64.     CROSS(start_norm, axis, dir);
  65.     divisor = lib_normalize_vector(start_norm);
  66.  
  67.     if (ABSOLUTE(divisor) < EPSILON2) {
  68.     SET_COORD3(dir, 1.0, 0.0, 0.0);
  69.     CROSS(start_norm, axis, dir);
  70.     lib_normalize_vector(start_norm);
  71.     }
  72.  
  73.     start_radius[0][X] = start_norm[X] * base_pt[W];
  74.     start_radius[0][Y] = start_norm[Y] * base_pt[W];
  75.     start_radius[0][Z] = start_norm[Z] * base_pt[W];
  76.     ADD3_COORD3(vert[2], base_pt, start_radius[0]);
  77.  
  78.     start_radius[1][X] = start_norm[X] * apex_pt[W];
  79.     start_radius[1][Y] = start_norm[Y] * apex_pt[W];
  80.     start_radius[1][Z] = start_norm[Z] * apex_pt[W];
  81.     ADD3_COORD3(vert[1], apex_pt, start_radius[1]);
  82.  
  83.     COPY_COORD3(norm[2], start_norm);
  84.     COPY_COORD3(norm[1], start_norm);
  85.  
  86.     delta_angle = 2.0 * PI / (double)(2*gU_resolution);
  87.     for (i=1,angle=delta_angle;i<=2*gU_resolution;++i,angle+=delta_angle) {
  88.     lib_create_axis_rotate_matrix(mx, norm_axis, angle);
  89.     lib_invert_matrix(nmx, mx);
  90.     lib_transform_point(vert[0], start_radius[1], mx);
  91.     ADD2_COORD3(vert[0], apex_pt);
  92.     lib_transform_normal(norm[0], start_norm, nmx);
  93.     lib_output_polypatch(3, vert, norm);
  94.     COPY_COORD3(vert[1], vert[0]);
  95.     COPY_COORD3(norm[1], norm[0]);
  96.     lib_transform_point(vert[0], start_radius[0], mx);
  97.     ADD2_COORD3(vert[0], base_pt);
  98.     lib_output_polypatch(3, vert, norm);
  99.  
  100.     COPY_COORD3(vert[2], vert[0]);
  101.     COPY_COORD3(norm[2], norm[0]);
  102.  
  103.     PLATFORM_MULTITASK();
  104.     }
  105. }
  106.  
  107. /*-----------------------------------------------------------------*/
  108. static void
  109. disc_evaluator(trans, theta, v, r, vert)
  110.     MATRIX trans;
  111.     double theta, v, r;
  112.     COORD3 vert;
  113. {
  114.     COORD3 tvert;
  115.  
  116.     /* Compute the position of the point */
  117.     SET_COORD3(tvert, (r + v) * cos(theta), (r + v) * sin(theta), 0.0);
  118.     lib_transform_point(vert, tvert, trans);
  119. }
  120.  
  121. /*-----------------------------------------------------------------*/
  122. void
  123. lib_output_polygon_disc(center, normal, iradius, oradius)
  124.     COORD3 center, normal;
  125.     double iradius, oradius;
  126. {
  127.     double u, v, delta_u, delta_v;
  128.     MATRIX mx, imx;
  129.     int i, j;
  130.     COORD3 norm, vert[4];
  131.  
  132.     COPY_COORD3(norm, normal);
  133.     if ( lib_normalize_vector(norm) < EPSILON2) {
  134.     fprintf(stderr, "Bad disc normal\n");
  135.     exit(1);
  136.     }
  137.     lib_create_canonical_matrix(mx, imx, center, norm);
  138.     delta_u = 2.0 * PI / (double)(4 * gU_resolution);
  139.     delta_v = (oradius - iradius) / (double)(gV_resolution);
  140.  
  141.     /* Dump out polygons */
  142.     for (i=0,u=0.0;i<4*gU_resolution;i++,u+=delta_u) {
  143.     PLATFORM_MULTITASK();
  144.     for (j=0,v=0.0;j<gV_resolution;j++,v+=delta_v) {
  145.         disc_evaluator(imx, u, v, iradius, vert[3]);
  146.         disc_evaluator(imx, u+delta_u, v, iradius, vert[2]);
  147.         disc_evaluator(imx, u+delta_u, v+delta_v, iradius, vert[1]);
  148.         disc_evaluator(imx, u, v+delta_v, iradius, vert[0]);
  149.         lib_output_polygon(4, vert);
  150.     }
  151.     }
  152. }
  153.  
  154. /*-----------------------------------------------------------------*/
  155. void
  156. lib_output_polygon_sphere(center_pt)
  157.     COORD4 center_pt;
  158. {
  159.     double  angle;
  160.     COORD3  edge_norm[3], edge_pt[3];
  161.     long    num_face, num_edge, num_tri, num_vert;
  162.     COORD3  *x_axis, *y_axis, **pt;
  163.     COORD3  mid_axis;
  164.     MATRIX  rot_mx;
  165.     long    u_pol, v_pol;
  166.  
  167.     /* Allocate storage for the polygon vertices */
  168.     x_axis = (COORD3 *)malloc((gU_resolution+1) * sizeof(COORD3));
  169.     y_axis = (COORD3 *)malloc((gV_resolution+1) * sizeof(COORD3));
  170.     pt     = (COORD3 **)malloc((gU_resolution+1) * sizeof(COORD3 *));
  171.     if (x_axis == NULL || y_axis == NULL || pt == NULL) {
  172.     fprintf(stderr, "Failed to allocate polygon data\n");
  173.     exit(1);
  174.     }
  175.  
  176.     for (num_edge=0;num_edge<gU_resolution+1;num_edge++) {
  177.     pt[num_edge] = (COORD3 *)malloc((gV_resolution+1) * sizeof(COORD3));
  178.     if (pt[num_edge] == NULL) {
  179.         fprintf(stderr, "Failed to allocate polygon data\n");
  180.         exit(1);
  181.     }
  182.     }
  183.  
  184.     /* calculate axes used to find grid points */
  185.     for (num_edge=0;num_edge<=gU_resolution;++num_edge) {
  186.     angle = (PI/4.0) * (2.0*(double)num_edge/gU_resolution - 1.0);
  187.     mid_axis[X] = 1.0; mid_axis[Y] = 0.0; mid_axis[Z] = 0.0;
  188.     lib_create_rotate_matrix(rot_mx, Y_AXIS, angle);
  189.     lib_transform_vector(x_axis[num_edge], mid_axis, rot_mx);
  190.     }
  191.  
  192.     for (num_edge=0;num_edge<=gV_resolution;++num_edge) {
  193.     angle = (PI/4.0) * (2.0*(double)num_edge/gV_resolution - 1.0);
  194.     mid_axis[X] = 0.0; mid_axis[Y] = 1.0; mid_axis[Z] = 0.0;
  195.     lib_create_rotate_matrix(rot_mx, X_AXIS, angle);
  196.     lib_transform_vector(y_axis[num_edge], mid_axis, rot_mx);
  197.     }
  198.  
  199.     /* set up grid of points on +Z sphere surface */
  200.     for (u_pol=0;u_pol<=gU_resolution;++u_pol) {
  201.     for (v_pol=0;v_pol<=gU_resolution;++v_pol) {
  202.         CROSS(pt[u_pol][v_pol], x_axis[u_pol], y_axis[v_pol]);
  203.         lib_normalize_vector(pt[u_pol][v_pol]);
  204.     }
  205.     }
  206.  
  207.     for (num_face=0;num_face<6;++num_face) {
  208.     /* transform points to cube face */
  209.     for (u_pol=0;u_pol<=gU_resolution;++u_pol) {
  210.         for (v_pol=0;v_pol<=gV_resolution;++v_pol) {
  211.         lib_rotate_cube_face(pt[u_pol][v_pol], Z_AXIS, num_face);
  212.         }
  213.     }
  214.  
  215.     /* output grid */
  216.     for (u_pol=0;u_pol<gU_resolution;++u_pol) {
  217.         for (v_pol=0;v_pol<gV_resolution;++v_pol) {
  218.         PLATFORM_MULTITASK();
  219.         for (num_tri=0;num_tri<2;++num_tri) {
  220.             for (num_edge=0;num_edge<3;++num_edge) {
  221.             num_vert = (num_tri*2 + num_edge) % 4;
  222.             if (num_vert == 0) {
  223.                 COPY_COORD3(edge_pt[num_edge], pt[u_pol][v_pol]);
  224.             } else if ( num_vert == 1 ) {
  225.                 COPY_COORD3(edge_pt[num_edge], pt[u_pol][v_pol+1]);
  226.             } else if ( num_vert == 2 ) {
  227.                 COPY_COORD3(edge_pt[num_edge],pt[u_pol+1][v_pol+1]);
  228.             } else {
  229.                 COPY_COORD3(edge_pt[num_edge], pt[u_pol+1][v_pol]);
  230.             }
  231.             COPY_COORD3(edge_norm[num_edge], edge_pt[num_edge]);
  232.             edge_pt[num_edge][X] =
  233.                 edge_pt[num_edge][X] * center_pt[W] +
  234.                                center_pt[X];
  235.             edge_pt[num_edge][Y] =
  236.                 edge_pt[num_edge][Y] * center_pt[W] +
  237.                                center_pt[Y];
  238.             edge_pt[num_edge][Z] =
  239.                 edge_pt[num_edge][Z] * center_pt[W] +
  240.                                center_pt[Z];
  241.  
  242.             }
  243.             lib_output_polypatch(3, edge_pt, edge_norm);
  244.         }
  245.         }
  246.     }
  247.     }
  248.  
  249.     /* Release any memory used */
  250.     for (num_edge=0;num_edge<gU_resolution+1;num_edge++)
  251.     free(pt[num_edge]);
  252.     free(pt);
  253.     free(y_axis);
  254.     free(x_axis);
  255. }
  256.  
  257.  
  258. /*-----------------------------------------------------------------*/
  259. void
  260. lib_output_polygon_height(height, width, data, x0, x1, y0, y1, z0, z1)
  261.     int height, width;
  262.     float **data;
  263.     double x0, x1, y0, y1, z0, z1;
  264. {
  265.     int i, j;
  266.     double xdelta, zdelta;
  267.     COORD3 verts[3];
  268.  
  269.     xdelta = (x1 - x0) / (double)(width - 1);
  270.     zdelta = (z1 - z0) / (double)(height - 1);
  271.     for (i=0;i<height-1;i++) {
  272.         PLATFORM_MULTITASK();
  273.         for (j=0;j<width-1;j++) {
  274.         SET_COORD3(verts[0], x0 + j * xdelta, y0 + data[i][j],
  275.                z0 + i * zdelta);
  276.         SET_COORD3(verts[1], x0 + (j+1) * xdelta, y0 + data[i][j+1],
  277.                z0 + i * zdelta);
  278.         SET_COORD3(verts[2], x0 + (j+1) * xdelta, y0 + data[i+1][j+1],
  279.                z0 + (i + 1) * zdelta);
  280.         lib_output_polygon(3, verts);
  281.         COPY_COORD3(verts[1], verts[2]);
  282.         SET_COORD3(verts[2], x0 + j * xdelta, y0 + data[i+1][j],
  283.                z0 + (i + 1) * zdelta);
  284.         lib_output_polygon(3, verts);
  285.         }
  286.     }
  287. }
  288.  
  289. /*-----------------------------------------------------------------*/
  290. static void
  291. torus_evaluator(trans, theta, phi, r0, r1, vert, norm)
  292.     MATRIX trans;
  293.     double theta, phi, r0, r1;
  294.     COORD3 vert, norm;
  295. {
  296.     COORD3 v0, v1, tvert, tnorm;
  297.  
  298.     /* Compute the position of the point */
  299.     SET_COORD3(tvert, (r0 + r1 * sin(theta)) * cos(phi),
  300.               (r0 + r1 * sin(theta)) * sin(phi),
  301.               r1 * cos(theta));
  302.     /* Compute the normal at that point */
  303.     SET_COORD3(v0, r1*cos(theta)*cos(phi),
  304.            r1*cos(theta)*sin(phi),
  305.           -r1*sin(theta));
  306.     SET_COORD3(v1,-(r0+r1*sin(theta))*sin(phi),
  307.            (r0+r1*sin(theta))*cos(phi),
  308.            0.0);
  309.     CROSS(tnorm, v0, v1);
  310.     lib_normalize_vector(tnorm);
  311.     lib_transform_point(vert, tvert, trans);
  312.     lib_transform_vector(norm, tnorm, trans);
  313. }
  314.  
  315. /*-----------------------------------------------------------------*/
  316. void
  317. lib_output_polygon_torus(center, normal, iradius, oradius)
  318.     COORD3 center, normal;
  319.     double iradius, oradius;
  320. {
  321.     double u, v, delta_u, delta_v;
  322.     MATRIX mx, imx;
  323.     int i, j;
  324.     COORD3 vert[4], norm[4];
  325.  
  326.     if ( lib_normalize_vector(normal) < EPSILON2) {
  327.     fprintf(stderr, "Bad torus normal\n");
  328.     exit(1);
  329.     }
  330.     lib_create_canonical_matrix(mx, imx, center, normal);
  331.     delta_u = 2.0 * PI / (double)gU_resolution;
  332.     delta_v = 2.0 * PI / (double)gV_resolution;
  333.  
  334.     /* Dump out polygons */
  335.     for (i=0,u=0.0;i<gU_resolution;i++,u+=delta_u) {
  336.         PLATFORM_MULTITASK();
  337.         for (j=0,v=0.0;j<gV_resolution;j++,v+=delta_v) {
  338.         torus_evaluator(imx, u, v, iradius, oradius, vert[2], norm[2]);
  339.         torus_evaluator(imx, u, v+delta_v, iradius, oradius,
  340.             vert[1], norm[1]);
  341.         torus_evaluator(imx, u+delta_u, v+delta_v,
  342.             iradius, oradius, vert[0], norm[0]);
  343.         lib_output_polypatch(3, vert, norm);
  344.         COPY_COORD3(vert[1], vert[0]);
  345.         COPY_COORD3(norm[1], norm[0]);
  346.         torus_evaluator(imx, u+delta_u, v, iradius, oradius,
  347.             vert[0], norm[0]);
  348.         lib_output_polypatch(3, vert, norm);
  349.         }
  350.     }
  351. }
  352. /*-----------------------------------------------------------------*/
  353. /* Generate a box as a set of 4-sided polygons */
  354. void
  355. lib_output_polygon_box(p1, p2)
  356.     COORD3 p1, p2;
  357. {
  358.     COORD3 box_verts[4];
  359.  
  360.     /* Sides */
  361.     SET_COORD3(box_verts[0], p1[X], p1[Y], p1[Z]);
  362.     SET_COORD3(box_verts[1], p1[X], p1[Y], p2[Z]);
  363.     SET_COORD3(box_verts[2], p1[X], p2[Y], p2[Z]);
  364.     SET_COORD3(box_verts[3], p1[X], p2[Y], p1[Z]);
  365.     lib_output_polygon(4, box_verts);
  366.     SET_COORD3(box_verts[0], p2[X], p1[Y], p2[Z]);
  367.     SET_COORD3(box_verts[1], p2[X], p1[Y], p1[Z]);
  368.     SET_COORD3(box_verts[2], p2[X], p2[Y], p1[Z]);
  369.     SET_COORD3(box_verts[3], p2[X], p2[Y], p2[Z]);
  370.     lib_output_polygon(4, box_verts);
  371.  
  372.     /* Front/Back */
  373.     SET_COORD3(box_verts[0], p1[X], p1[Y], p1[Z]);
  374.     SET_COORD3(box_verts[3], p2[X], p1[Y], p1[Z]);
  375.     SET_COORD3(box_verts[2], p2[X], p2[Y], p1[Z]);
  376.     SET_COORD3(box_verts[1], p1[X], p2[Y], p1[Z]);
  377.     lib_output_polygon(4, box_verts);
  378.     SET_COORD3(box_verts[0], p2[X], p1[Y], p2[Z]);
  379.     SET_COORD3(box_verts[3], p1[X], p1[Y], p2[Z]);
  380.     SET_COORD3(box_verts[2], p1[X], p2[Y], p2[Z]);
  381.     SET_COORD3(box_verts[1], p2[X], p2[Y], p2[Z]);
  382.     lib_output_polygon(4, box_verts);
  383.  
  384.     /* Top/Bottom */
  385.     SET_COORD3(box_verts[0], p1[X], p1[Y], p1[Z]);
  386.     SET_COORD3(box_verts[3], p1[X], p1[Y], p2[Z]);
  387.     SET_COORD3(box_verts[2], p2[X], p1[Y], p2[Z]);
  388.     SET_COORD3(box_verts[1], p2[X], p1[Y], p1[Z]);
  389.     lib_output_polygon(4, box_verts);
  390.     SET_COORD3(box_verts[0], p2[X], p2[Y], p1[Z]);
  391.     SET_COORD3(box_verts[3], p2[X], p2[Y], p2[Z]);
  392.     SET_COORD3(box_verts[2], p1[X], p2[Y], p2[Z]);
  393.     SET_COORD3(box_verts[1], p1[X], p2[Y], p1[Z]);
  394.     lib_output_polygon(4, box_verts);
  395. }
  396.  
  397.  
  398. /*-----------------------------------------------------------------*/
  399. /* Given a polygon defined by vertices in verts, determine which of the
  400.    components of the vertex correspond to useful x and y coordinates - with
  401.    these we can pretend the polygon is 2D to do our work on it. */
  402. static void
  403. find_axes(verts)
  404.     COORD3 *verts;
  405. {
  406.     double P1[3], P2[3], x, y, z;
  407.  
  408.     P1[0] = VERT(1, 0) - VERT(0, 0);
  409.     P1[1] = VERT(1, 1) - VERT(0, 1);
  410.     P1[2] = VERT(1, 2) - VERT(0, 2);
  411.  
  412.     P2[0] = VERT(2, 0) - VERT(0, 0);
  413.     P2[1] = VERT(2, 1) - VERT(0, 1);
  414.     P2[2] = VERT(2, 2) - VERT(0, 2);
  415.  
  416.     /* Cross product - don't need to normalize cause we're only interested
  417.       in the size of the components */
  418.     x = fabs(P1[1] * P2[2] - P1[2] * P2[1]);
  419.     y = fabs(P1[2] * P2[0] - P1[0] * P2[2]);
  420.     z = fabs(P1[0] * P2[1] - P1[1] * P2[0]);
  421.  
  422.     if (x > y && x > z) {
  423.     gPoly_Axis1 = 1;
  424.     gPoly_Axis2 = 2;
  425.     } else if (y > x && y > z) {
  426.     gPoly_Axis1 = 0;
  427.     gPoly_Axis2 = 2;
  428.     } else {
  429.     gPoly_Axis1 = 0;
  430.     gPoly_Axis2 = 1;
  431.     }
  432. }
  433.  
  434. /*-----------------------------------------------------------------*/
  435. /* Find the left most vertex in the polygon that has vertices m ... n. */
  436. static int
  437. leftmost_vertex(m, n, verts)
  438.     int m, n;
  439.     COORD3 *verts;
  440. {
  441.     int l, i;
  442.     double x;
  443.  
  444.     /* Assume the first vertex is the farthest to the left */
  445.     l = m;
  446.     x = VERT(m, gPoly_Axis1);
  447.  
  448.     /* Now see if any of the others are farther to the left */
  449.     for (i=m+1;i<=n;i++) {
  450.        if (VERT(i, gPoly_Axis1) < x) {
  451.        l = i;
  452.        x = VERT(i, gPoly_Axis1);
  453.        }
  454.     }
  455.     return l;
  456. }
  457.  
  458. /*-----------------------------------------------------------------*/
  459. /* Given the leftmost vertex in a polygon, this routine finds another vertex
  460.    can be used to safely split the polygon. */
  461. static int
  462. split_vertex(l, la, lb, m, n, verts)
  463.     int l, la, lb, m, n;
  464.     COORD3 *verts;
  465. {
  466.     int t, k, lpu, lpl;
  467.     double yu, yl;
  468.  
  469.     yu = MAX(VERT(l, gPoly_Axis2), MAX(VERT(la, gPoly_Axis2), VERT(lb, gPoly_Axis2)));
  470.     yl = MIN(VERT(l, gPoly_Axis2), MIN(VERT(la, gPoly_Axis2), VERT(lb, gPoly_Axis2)));
  471.     if (VERT(lb, gPoly_Axis2) > VERT(la, gPoly_Axis2)) {
  472.     lpu = lb;
  473.     lpl = la;
  474.     } else {
  475.     lpu = la;
  476.     lpl = lb;
  477.     }
  478.     t = (VERT(lb, gPoly_Axis1) > VERT(la, gPoly_Axis1) ? lb : la);
  479.     for (k=m;k<n;k++) {
  480.     if (k != la && k != l && k != lb) {
  481.         if (VERT(k, gPoly_Axis2) <= yu && VERT(k, gPoly_Axis2) >= yl) {
  482.         if (VERT(k, gPoly_Axis1) < VERT(t, gPoly_Axis1) &&
  483.             ((VERT(k, gPoly_Axis2) - VERT(l, gPoly_Axis2)) *
  484.              (VERT(lpu, gPoly_Axis1) - VERT(l, gPoly_Axis1))) <=
  485.             ((VERT(lpu, gPoly_Axis2) - VERT(l, gPoly_Axis2)) *
  486.              (VERT(k, gPoly_Axis1) - VERT(l, gPoly_Axis1)))) {
  487.             if (((VERT(k, gPoly_Axis2) - VERT(l, gPoly_Axis2)) *
  488.               (VERT(lpl, gPoly_Axis1) - VERT(l, gPoly_Axis1))) >=
  489.              ((VERT(lpl, gPoly_Axis2) - VERT(l, gPoly_Axis2)) *
  490.              (VERT(k, gPoly_Axis1) - VERT(l, gPoly_Axis1)))) {
  491.             t = k;
  492.             }
  493.         }
  494.         }
  495.     }
  496.     }
  497.     return t;
  498. }
  499.  
  500. /*-----------------------------------------------------------------*/
  501. /* Test polygon vertices to see if they are linear */
  502. static int
  503. linear_vertices(m, n, verts)
  504.     int m, n;
  505.     COORD3 *verts;
  506. {
  507. #if defined (applec)
  508. #pragma unused (m,n,verts)
  509. #endif /* applec */
  510.     /* Not doing anything right now */
  511.     return 0;
  512. }
  513.  
  514. /*-----------------------------------------------------------------*/
  515. /* Shift vertex indices around to make two polygons out of one. */
  516. static void
  517. perform_split(m, m1, n, n1)
  518.     int n, n1, m, m1;
  519. {
  520.     int i, j, k;
  521.  
  522.     k = n + 3 - m;
  523.     /* Move the new polygon up over the place the current one sits */
  524.     for (j=m1;j<=n1;j++) gPoly_vbuffer[j+k] = gPoly_vbuffer[j];
  525.  
  526.     /* Move top part of remaining polygon */
  527.     for (j=n;j>=n1;j--) gPoly_vbuffer[j+2] = gPoly_vbuffer[j];
  528.  
  529.     /* Move bottom part of remaining polygon */
  530.     k = n1 - m1 + 1;
  531.     for (j=m1;j>=m;j--) gPoly_vbuffer[j+k] = gPoly_vbuffer[j];
  532.  
  533.     /* Copy the new polygon so that it sits before the remaining polygon */
  534.     i = n + 3 - m;
  535.     k = m - m1;
  536.     for (j=m1;j<=n1;j++) gPoly_vbuffer[j+k] = gPoly_vbuffer[j+i];
  537. }
  538.  
  539. /*-----------------------------------------------------------------*/
  540. /* Copy an indirectly referenced triangle into the output triangle buffer */
  541. static void
  542. add_new_triangle(m, verts, norms, out_cnt, out_verts, out_norms)
  543.     int m, *out_cnt;
  544.     COORD3 *verts, *norms, **out_verts, **out_norms;
  545. {
  546.     if (out_verts != NULL) {
  547.     COPY_COORD3(out_verts[*out_cnt][0], verts[gPoly_vbuffer[m]]);
  548.     COPY_COORD3(out_verts[*out_cnt][1], verts[gPoly_vbuffer[m+1]]);
  549.     COPY_COORD3(out_verts[*out_cnt][2], verts[gPoly_vbuffer[m+2]]);
  550.     }
  551.     if (out_norms != NULL) {
  552.     COPY_COORD3(out_norms[*out_cnt][0], norms[gPoly_vbuffer[m]]);
  553.     COPY_COORD3(out_norms[*out_cnt][1], norms[gPoly_vbuffer[m+1]]);
  554.     COPY_COORD3(out_norms[*out_cnt][2], norms[gPoly_vbuffer[m+2]]);
  555.     }
  556.     *out_cnt += 1;
  557. }
  558.  
  559. /*-----------------------------------------------------------------*/
  560. static void
  561. split_buffered_polygon(cnt, verts, norms, out_cnt, out_verts, out_norms)
  562.     int cnt, *out_cnt;
  563.     COORD3 *verts, *norms, **out_verts, **out_norms;
  564. {
  565.     int i, m, m1, n, n1;
  566.     int l, la, lb, ls;
  567.  
  568.     /* No triangles to start with */
  569.     *out_cnt = 0;
  570.  
  571.     /* Initialize the polygon splitter */
  572.     gPoly_end[0] = -1;
  573.     gPoly_end[1] = cnt-1;
  574.  
  575.     /* Split and push polygons until they turn into triangles */
  576.     for (i=1;i>0;) {
  577.     m = gPoly_end[i-1] + 1;
  578.     n = gPoly_end[i];
  579.     if (n - m == 2) {
  580.         if (!linear_vertices(m, n, verts)) {
  581.         add_new_triangle(m, verts, norms, out_cnt,
  582.             out_verts, out_norms);
  583.         }
  584.         i = i - 1;
  585.     } else {
  586.         l = leftmost_vertex(m, n, verts);
  587.         la = (l == n ? m : l + 1);
  588.         lb = (l == m ? n : l - 1);
  589.         ls = split_vertex(l, la, lb, m, n, verts);
  590.         if (ls == la || ls == lb) {
  591.         m1 = (la < lb ? la : lb);
  592.         n1 = (la > lb ? la : lb);
  593.         } else {
  594.         m1 = (l < ls ? l : ls);
  595.         n1 = (l > ls ? l : ls);
  596.         }
  597.         perform_split(m, m1, n, n1);
  598.         gPoly_end[i++] = m + n1 - m1;
  599.         gPoly_end[i] = n + 2;
  600.     }
  601.     }
  602. }
  603.  
  604. /*-----------------------------------------------------------------*/
  605. /*
  606.  * Split an arbitrary polygon into triangles.
  607.  */
  608. static void
  609. split_polygon(n, vert, norm)
  610.     int n;
  611.     COORD3 *vert, *norm;
  612. {
  613.     COORD4 tvert[3], v0, v1;
  614.     COORD3 **out_verts, **out_norms;
  615.     MATRIX nmx, txmat;
  616.     int i, ii, j ;
  617.     int t, out_n;
  618.     object_ptr new_object;
  619.  
  620.     /* Can't split a NULL vertex list */
  621.     if (vert == NULL) return;
  622.     if (gPoly_vbuffer == NULL) { /* [esp] Added error */
  623.     lib_storage_initialize();
  624.     /* [are] removed error, go and initialize if it hasn't been done. */
  625.     }
  626.  
  627.     /* Allocate space to hold the intermediate polygon stacks */
  628.     out_verts = (COORD3 **)malloc((n - 2) * sizeof(COORD3 *));
  629.     if (norm != NULL)
  630.     out_norms = (COORD3 **)malloc((n - 2) * sizeof(COORD3 *));
  631.     else
  632.     out_norms = NULL;
  633.     for (i=0;i<n-2;i++) {
  634.     out_verts[i] = (COORD3 *)malloc(3 * sizeof(COORD3));
  635.     if (norm != NULL)
  636.         out_norms[i] = (COORD3 *)malloc(3 * sizeof(COORD3));
  637.     }
  638.  
  639.     /* Start with a strict identity of vertices in verts and vertices in
  640.        the polygon buffer */
  641.     for (i=0;i<n;i++) gPoly_vbuffer[i] = i;
  642.  
  643.     /* Make sure we know which axes to look at */
  644.     find_axes(vert);
  645.  
  646.     out_n = 0;
  647.     split_buffered_polygon(n, vert, norm, &out_n, out_verts, out_norms);
  648.  
  649.    if (lib_tx_active()) {
  650.       /* Perform transformations of the vertices and normals of
  651.      the polygon(s) */
  652.       lib_get_current_tx(txmat);
  653.       lib_invert_matrix(nmx, txmat);
  654.       for (t=0;t<out_n;t++)
  655.      for (i=0;i<3;i++) {
  656.         lib_transform_point(out_verts[t][i], out_verts[t][i], txmat);
  657.         if (out_norms != NULL)
  658.            lib_transform_normal(out_norms[t][i], out_norms[t][i], nmx);
  659.         }
  660.       }
  661.  
  662.     /* Now output the triangles that we generated */
  663.     for (t=0;t<out_n;t++) {
  664.     PLATFORM_MULTITASK();
  665.     if (gRT_out_format == OUTPUT_DELAYED ||
  666.         gRT_out_format == OUTPUT_PLG) {
  667.         /* Save all the pertinent information */
  668.         new_object = (object_ptr)malloc(sizeof(struct object_struct));
  669.         if (new_object == NULL) return;
  670.         new_object->tx = NULL;
  671.         if (norm == NULL) {
  672.         new_object->object_type  = POLYGON_OBJ;
  673.         new_object->object_data.polygon.tot_vert = 3;
  674.         new_object->object_data.polygon.vert =
  675.             (COORD3 *)malloc(3 * sizeof(COORD3));
  676.         if (new_object->object_data.polygon.vert == NULL) return;
  677.         } else {
  678.         new_object->object_type  = POLYPATCH_OBJ;
  679.         new_object->object_data.polypatch.tot_vert = 3;
  680.         new_object->object_data.polypatch.vert =
  681.             (COORD3 *)malloc(3 * sizeof(COORD3));
  682.         if (new_object->object_data.polypatch.vert == NULL) return;
  683.         new_object->object_data.polypatch.norm =
  684.             (COORD3 *)malloc(3 * sizeof(COORD3));
  685.         if (new_object->object_data.polypatch.norm == NULL) return;
  686.         }
  687.         new_object->curve_format = OUTPUT_PATCHES;
  688.         new_object->surf_index   = gTexture_count;
  689.         for (i=0;i<3;i++) {
  690.         if (norm == NULL)
  691.             COPY_COORD3(new_object->object_data.polygon.vert[i],
  692.                 out_verts[t][i])
  693.         else {
  694.             COPY_COORD3(new_object->object_data.polypatch.vert[i],
  695.                 out_verts[t][i])
  696.             COPY_COORD3(new_object->object_data.polypatch.norm[i],
  697.                 out_norms[t][i])
  698.         }
  699.         }
  700.        if (gRT_out_format == OUTPUT_PLG) {
  701.            /* We are currently in the process of turning objects
  702.           into a stack of polygons.  Since we don't want to
  703.           put these polygons back onto the original stack of
  704.           objects, we put them into gPolygon_stack */
  705.            new_object->next_object = gPolygon_stack;
  706.            gPolygon_stack = new_object;
  707.         }
  708.        else {
  709.            new_object->next_object = gLib_objects;
  710.            gLib_objects = new_object;
  711.        }
  712.     } else {
  713.         switch (gRT_out_format) {
  714.         case OUTPUT_VIDEO:
  715.             /* First make sure the display has been opened for
  716.              * drawing
  717.              */
  718.             if (!gView_init_flag) {
  719.             lib_create_view_matrix(gViewpoint.tx, gViewpoint.from, gViewpoint.at,
  720.                                gViewpoint.up, gViewpoint.resx, gViewpoint.resy,
  721.                                gViewpoint.angle, gViewpoint.aspect);
  722.             display_init(gViewpoint.resx, gViewpoint.resy, gBkgnd_color);
  723.             gView_init_flag = 1;
  724.             }
  725.             /* Step through each segment of the polygon, projecting it
  726.                onto the screen. */
  727.             for (i=0;i<3;i++) {
  728.             COPY_COORD3(tvert[0], out_verts[t][i]);
  729.             tvert[0][W] = 1.0;
  730.             lib_transform_coord(v0, tvert[0], gViewpoint.tx);
  731.             COPY_COORD3(tvert[1], out_verts[t][(i+1)%3]);
  732.             tvert[1][W] = 1.0;
  733.             lib_transform_coord(v1, tvert[1], gViewpoint.tx);
  734.             /* Do the perspective transform on the points */
  735.             v0[X] /= v0[W]; v0[Y] /= v0[W];
  736.             v1[X] /= v1[W]; v1[Y] /= v1[W];
  737.             if (lib_clip_to_box(v0, v1, gView_bounds))
  738.                 display_line((int)v0[X], (int)v0[Y],
  739.                         (int)v1[X], (int)v1[Y], gFgnd_color);
  740.             }
  741.             break;
  742.  
  743.         case OUTPUT_NFF:
  744.             if (norm == NULL) {
  745.             fprintf(gOutfile, "p 3\n");
  746.             for (i=0;i<3;++i) {
  747.                 fprintf(gOutfile, "%g %g %g\n",
  748.                     out_verts[t][i][X], out_verts[t][i][Y],
  749.                     out_verts[t][i][Z]);
  750.             }
  751.             } else {
  752.             fprintf(gOutfile, "pp 3\n");
  753.             for (i=0;i<3;++i) {
  754.                 fprintf(gOutfile, "%g %g %g %g %g %g\n",
  755.                     out_verts[t][i][X], out_verts[t][i][Y],
  756.                     out_verts[t][i][Z], out_norms[t][i][X],
  757.                     out_norms[t][i][Y], out_norms[t][i][Z]);
  758.             }
  759.             }
  760.            break;
  761.  
  762.         case OUTPUT_POVRAY_10:
  763.         case OUTPUT_POVRAY_20:
  764.             tab_indent();
  765.             fprintf(gOutfile, "object {\n");
  766.             tab_inc();
  767.  
  768.             tab_indent();
  769.             if (norm == NULL)
  770.             fprintf(gOutfile, "triangle {\n");
  771.             else
  772.             fprintf(gOutfile, "smooth_triangle {\n");
  773.             tab_inc();
  774.  
  775.             for (i=0;i<3;++i) {
  776.             tab_indent();
  777.             if (gRT_out_format == OUTPUT_POVRAY_10) {
  778.                 fprintf(gOutfile, "<%g %g %g>",
  779.                    out_verts[t][i][X],
  780.                    out_verts[t][i][Y],
  781.                    out_verts[t][i][Z]);
  782.                 if (norm != NULL)
  783.                 fprintf(gOutfile, " <%g %g %g>",
  784.                        out_norms[t][i][X],
  785.                        out_norms[t][i][Y],
  786.                        out_norms[t][i][Z]);
  787.             } else {
  788.                 fprintf(gOutfile, "<%g, %g, %g>",
  789.                    out_verts[t][i][X],
  790.                    out_verts[t][i][Y],
  791.                    out_verts[t][i][Z]);
  792.                 if (norm != NULL)
  793.                    fprintf(gOutfile, " <%g, %g, %g>",
  794.                       out_norms[t][i][X],
  795.                       out_norms[t][i][Y],
  796.                       out_norms[t][i][Z]);
  797.                 if (i < 2)
  798.                    fprintf(gOutfile, ",");
  799.             }
  800.             fprintf(gOutfile, "\n");
  801.             } /*for*/
  802.  
  803.             tab_dec();
  804.             tab_indent();
  805.             fprintf(gOutfile, "} // tri\n");
  806.  
  807.             if (gTexture_name != NULL) {
  808.                tab_indent();
  809.                fprintf(gOutfile, "texture { %s }\n", gTexture_name);
  810.             }
  811.  
  812.             tab_dec();
  813.             tab_indent();
  814.             fprintf(gOutfile, "} // object\n");
  815.  
  816.             fprintf(gOutfile, "\n");
  817.             break;
  818.  
  819.         case OUTPUT_POLYRAY:
  820.             if (norm == NULL) {
  821.             tab_indent();
  822.             fprintf(gOutfile, "object { polygon 3,");
  823.             for (i=0;i<3;i++) {
  824.                 fprintf(gOutfile, " <%g, %g, %g>",
  825.                     out_verts[t][i][X], out_verts[t][i][Y],
  826.                     out_verts[t][i][Z]);
  827.                 if (i < 2)
  828.                 fprintf(gOutfile, ", ");
  829.             }
  830.             } else {
  831.             tab_indent();
  832.             fprintf(gOutfile, "object { patch ");
  833.             for (i=0;i<3;i++) {
  834.                 j = (i == 0 ? 0 : (i == 1 ? 2 : 1));
  835.                 fprintf(gOutfile, " <%g, %g, %g>, <%g, %g, %g>",
  836.                     out_verts[t][j][X], out_verts[t][j][Y],
  837.                     out_verts[t][j][Z], out_norms[t][j][X],
  838.                     out_verts[t][j][Y], out_norms[t][j][Z]);
  839.                 if (i < 2)
  840.                 fprintf(gOutfile, ", ");
  841.             }
  842.             }
  843.             if (gTexture_name != NULL)
  844.             fprintf(gOutfile, " %s", gTexture_name);
  845.             fprintf(gOutfile, " }\n");
  846.             fprintf(gOutfile, "\n");
  847.             break;
  848.  
  849.         case OUTPUT_VIVID:
  850.             if (norm == NULL) {
  851.             tab_indent();
  852.             fprintf(gOutfile, "polygon { points 3 ");
  853.             for (i=0;i<3;i++) {
  854.                 fprintf(gOutfile, " vertex %g %g %g ",
  855.                     out_verts[t][i][X], out_verts[t][i][Y],
  856.                     out_verts[t][i][Z]);
  857.             }
  858.             } else {
  859.             fprintf(gOutfile, "patch {");
  860.             for (i=0;i<3;++i) {
  861.                 fprintf(gOutfile,
  862.                     " vertex %g %g %g  normal %g %g %g ",
  863.                     out_verts[t][i][X], out_verts[t][i][Y],
  864.                     out_verts[t][i][Z], out_norms[t][i][X],
  865.                     out_norms[t][i][Y], out_norms[t][i][Z]);
  866.             }
  867.             }
  868.             fprintf(gOutfile, " }\n");
  869.             fprintf(gOutfile, "\n");
  870.             break;
  871.  
  872.         case OUTPUT_QRT:
  873.             /* Doesn't matter if there are vertex normals,
  874.              * QRT can't use them.
  875.              */
  876.             fprintf(gOutfile, "TRIANGLE ( ");
  877.             fprintf(gOutfile, "loc = (%g, %g, %g), ",
  878.                   out_verts[t][0][X], out_verts[t][0][Y],
  879.                   out_verts[t][0][Z]);
  880.             fprintf(gOutfile, "vect1 = (%g, %g, %g), ",
  881.                   out_verts[t][1][X] - out_verts[t][0][X],
  882.                   out_verts[t][1][Y] - out_verts[t][0][Y],
  883.                   out_verts[t][1][Z] - out_verts[t][0][Z]);
  884.             fprintf(gOutfile, "vect2 = (%g, %g, %g) ",
  885.                   out_verts[t][2][X] - out_verts[t][0][X],
  886.                   out_verts[t][2][Y] - out_verts[t][0][Y],
  887.                   out_verts[t][2][Z] - out_verts[t][0][Z]);
  888.             fprintf(gOutfile, " );\n");
  889.             break;
  890.  
  891.         case OUTPUT_RAYSHADE:
  892.             fprintf(gOutfile, "triangle ");
  893.             if (gTexture_name != NULL)
  894.             fprintf(gOutfile, "%s ", gTexture_name);
  895.             for (i=0;i<3;i++) {
  896.             fprintf(gOutfile, "%g %g %g ",
  897.                 out_verts[t][i][X], out_verts[t][i][Y],
  898.                 out_verts[t][i][Z]);
  899.             if (norm != NULL)
  900.                 fprintf(gOutfile, "%g %g %g ",
  901.                     out_norms[t][i][X], out_norms[t][i][Y],
  902.                     out_norms[t][i][Z]);
  903.             }
  904.             fprintf(gOutfile, "\n");
  905.             break;
  906.  
  907.         case OUTPUT_ART:
  908.             tab_indent();
  909.             fprintf(gOutfile, "polygon {\n");
  910.             tab_inc();
  911.  
  912.             tab_indent();
  913.             for (i=0;i<3;i++) {
  914.             tab_indent();
  915.             fprintf(gOutfile, "vertex(%f, %f, %f)",
  916.                 out_verts[t][i][X], out_verts[t][i][Y],
  917.                 out_verts[t][i][Z]);
  918.             if (norm != NULL)
  919.                 fprintf(gOutfile, ", (%f, %f, %f)\n",
  920.                     out_norms[t][i][X], out_norms[t][i][Y],
  921.                     out_norms[t][i][Z]);
  922.             else
  923.                 fprintf(gOutfile, "\n");
  924.             }
  925.             tab_dec();
  926.             tab_indent();
  927.             fprintf(gOutfile, "}\n");
  928.             fprintf(gOutfile, "\n");
  929.             break;
  930.  
  931.         case OUTPUT_RTRACE:
  932.             if (norm == NULL) {
  933.             fprintf(gOutfile, "5 %d %g 0 0 0 1 1 1 -\n",
  934.                 gTexture_count, gTexture_ior);
  935.             fprintf(gOutfile, "3 1 2 3\n\n");
  936.             } else {
  937.             fprintf(gOutfile, "6 %d %g 0 0 0 1 1 1 -\n",
  938.                 gTexture_count, gTexture_ior);
  939.             }
  940.             for (i=0;i<3;i++) {
  941.             fprintf(gOutfile, "%g %g %g",
  942.                 out_verts[t][i][X], out_verts[t][i][Y],
  943.                 out_verts[t][i][Z]);
  944.             if (norm != NULL) {
  945.                 fprintf(gOutfile, " %g %g %g",
  946.                     out_norms[t][i][X], out_norms[t][i][Y],
  947.                     out_norms[t][i][Z]);
  948.             }
  949.             fprintf(gOutfile, "\n");
  950.             }
  951.             fprintf(gOutfile, "\n");
  952.             break;
  953.  
  954.         case OUTPUT_RAWTRI:
  955.             for (i=0;i<3;++i) {
  956.             fprintf(gOutfile, "%-10.5g %-10.5g %-10.5g  ",
  957.                 out_verts[t][i][X], out_verts[t][i][Y],
  958.                 out_verts[t][i][Z]);
  959.             }
  960.  
  961. #ifdef RAWTRI_WITH_TEXTURES
  962.             /* raw triangle format extension to do textured raw
  963.              * triangles */
  964.             if (gTexture_name != NULL)
  965.             fprintf(gOutfile, "%s", gTexture_name);
  966.             else
  967.             /* for lack of a better name */
  968.             fprintf(gOutfile, "texNone");
  969. #endif /* RAWTRI_WITH_TEXTURES */
  970.  
  971.             fprintf(gOutfile, "\n");
  972.             break;
  973.  
  974.         case OUTPUT_OBJ:
  975.             /* First the vertices */
  976.             for (i=0;i<3;++i)
  977.                fprintf(gOutfile, "v %g %g %g\n",
  978.                 out_verts[t][i][X], out_verts[t][i][Y],
  979.                 out_verts[t][i][Z]);
  980.             if (norm != NULL)
  981.             for (i=0;i<3;++i)
  982.                 fprintf(gOutfile, "vn %g %g %g\n",
  983.                     out_norms[t][i][X], out_norms[t][i][Y],
  984.                     out_norms[t][i][Z]);
  985.             /* Then the face - note that we add one to the count
  986.                since Wavefront vertices start at 1, not 0. */
  987.             if (norm == NULL) {
  988.                fprintf(gOutfile, "f %d %d %d\n",
  989.                    gVertex_count+1, gVertex_count+2,
  990.                    gVertex_count+3);
  991.                gVertex_count += 3;
  992.                }
  993.             else {
  994.                fprintf(gOutfile, "f %d//%d %d//%d %d//%d\n",
  995.                    gVertex_count+1, gNormal_count+1,
  996.                    gVertex_count+2, gNormal_count+2,
  997.                    gVertex_count+3, gNormal_count+3);
  998.                gVertex_count += 3;
  999.                gNormal_count += 3;
  1000.                }
  1001.             break;
  1002.  
  1003.         case OUTPUT_RWX:
  1004.             /* First the vertices */
  1005.             for (i=0;i<3;++i) {
  1006.                tab_indent();
  1007.                fprintf(gOutfile, "Vertex %g %g %g",
  1008.                 out_verts[t][i][X], out_verts[t][i][Y],
  1009.                 out_verts[t][i][Z]);
  1010.                if (norm != NULL)
  1011.                fprintf(gOutfile, " Normal %g %g %g\n",
  1012.                    out_norms[t][i][X], out_norms[t][i][Y],
  1013.                    out_norms[t][i][Z]);
  1014.                else
  1015.               fprintf(gOutfile, "\n");
  1016.                }
  1017.  
  1018.             /* Then the face */
  1019.             tab_indent();
  1020.             fprintf(gOutfile, "Triangle %ld %ld %ld\n",
  1021.                 gVertex_count+1, gVertex_count+2,
  1022.                 gVertex_count+3);
  1023.             gVertex_count += 3;
  1024.             break;
  1025.  
  1026.         case OUTPUT_RIB:
  1027.             /* The order of the vertices has to be inverted for the
  1028.                LH system */
  1029.             tab_indent();
  1030.             fprintf(gOutfile, "Polygon \"P\" [\n");
  1031.             tab_inc();
  1032.             for (i=2;i>=0;i--)
  1033.             {
  1034.             tab_indent();
  1035.             fprintf(gOutfile, "%#g %#g %#g\n",
  1036.                   out_verts[t][i][X], out_verts[t][i][Y],
  1037.                   out_verts[t][i][Z]);
  1038.             }
  1039.             if (norm != NULL)
  1040.             {
  1041.             tab_dec();
  1042.             tab_indent();
  1043.             tab_inc();
  1044.             fprintf(gOutfile, "]  \"N\" [\n");
  1045.             for (i=2;i>=0;i--)
  1046.             {
  1047.                 /* Normals are also inverted in LH */
  1048.                 tab_indent();
  1049.                 fprintf(gOutfile, "%#g %#g %#g\n",
  1050.                      -out_norms[t][i][X], -out_norms[t][i][Y],
  1051.                      -out_norms[t][i][Z]);
  1052.             }
  1053.             }
  1054.             tab_dec();
  1055.             tab_indent();
  1056.             fprintf(gOutfile, "]\n");
  1057.             break;
  1058.  
  1059.         case OUTPUT_DXF:
  1060.             fprintf(gOutfile, "  0\n3DFACE\n  8\n0----\n" ) ;
  1061.             for (i=0;i<4;++i) {
  1062.             ii = (i == 3) ? 2 : i ;
  1063.             for (j=0;j<3;++j) {
  1064.                 fprintf(gOutfile, " %d%d\n%0.4f\n",j+1,i,
  1065.                     out_verts[t][ii][j] ) ;
  1066.             }
  1067.             }
  1068.             break;
  1069.  
  1070.         } /* switch */
  1071.     } /* else !OUTPUT_DELAYED */
  1072.     } /* else for loop */
  1073.  
  1074.     /* Clean up intermediate storage */
  1075.     for (i=0;i<n-2;i++) {
  1076.     free(out_verts[i]);
  1077.     if (norm != NULL)
  1078.         free(out_norms[i]);
  1079.     }
  1080.  
  1081.     free(out_verts);
  1082.     if (out_norms != NULL) free(out_norms);
  1083. }
  1084.  
  1085. /*-----------------------------------------------------------------*/
  1086. /*
  1087.  * Output polygon.  A polygon is defined by a set of vertices.  With these
  1088.  * databases, a polygon is defined to have all points coplanar.  A polygon has
  1089.  * only one side, with the order of the vertices being counterclockwise as you
  1090.  * face the polygon (right-handed coordinate system).
  1091.  *
  1092.  * The output format is always:
  1093.  *     "p" total_vertices
  1094.  *     vert1.x vert1.y vert1.z
  1095.  *     [etc. for total_vertices polygons]
  1096.  *
  1097.  */
  1098. void
  1099. lib_output_polygon(tot_vert, vert)
  1100.     int tot_vert;
  1101.     COORD3 vert[];
  1102. {
  1103.     object_ptr new_object;
  1104.     int num_vert, i, j;
  1105.     COORD3 x;
  1106.     COORD4 tvert[3], v0, v1;
  1107.     MATRIX txmat;
  1108.  
  1109.     /* First lets do a couple of checks to see if this is a valid polygon */
  1110.     for (i=0;i<tot_vert;) {
  1111.     /* If there are two adjacent coordinates that degenerate then
  1112.        collapse them down to one */
  1113.     SUB3_COORD3(x, vert[i], vert[(i+1)%tot_vert]);
  1114.     if (lib_normalize_vector(x) < EPSILON2) {
  1115.         for (j=i;j<tot_vert-1;j++)
  1116.         memcpy(&vert[j], &vert[j+1], sizeof(COORD4));
  1117.         tot_vert--;
  1118.     }
  1119.     else {
  1120.         i++;
  1121.     }
  1122.     }
  1123.  
  1124.     if (tot_vert < 3)
  1125.     /* No such thing as a poly that only has two sides */
  1126.     return;
  1127.  
  1128.     if (lib_tx_active()) {
  1129.     /* Perform transformations of the vertices and normals of
  1130.        the polygon(s) */
  1131.     lib_get_current_tx(txmat);
  1132.     for (i=0;i<tot_vert;i++)
  1133.         lib_transform_point(vert[i], vert[i], txmat);
  1134.     }
  1135.  
  1136.     if (gRT_out_format == OUTPUT_DELAYED) {
  1137.     /* Save all the pertinent information */
  1138.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  1139.     new_object->object_data.polygon.vert =
  1140.         (COORD3 *)malloc(tot_vert * sizeof(COORD3));
  1141.     if (new_object == NULL || new_object->object_data.polygon.vert == NULL)
  1142.         /* Quietly fail */
  1143.         return;
  1144.     new_object->object_type  = POLYGON_OBJ;
  1145.     new_object->curve_format = OUTPUT_PATCHES;
  1146.     new_object->surf_index   = gTexture_count;
  1147.     new_object->object_data.polygon.tot_vert = tot_vert;
  1148.     new_object->tx = NULL;
  1149.     for (i=0;i<tot_vert;i++)
  1150.         COPY_COORD3(new_object->object_data.polygon.vert[i], vert[i])
  1151.     new_object->next_object = gLib_objects;
  1152.     gLib_objects = new_object;
  1153.     } else {
  1154.     switch (gRT_out_format) {
  1155.         case OUTPUT_VIDEO:
  1156.         /* First make sure the display has been opened for drawing */
  1157.         if (!gView_init_flag) {
  1158.             lib_create_view_matrix(gViewpoint.tx, gViewpoint.from, gViewpoint.at,
  1159.                            gViewpoint.up, gViewpoint.resx, gViewpoint.resy,
  1160.                            gViewpoint.angle, gViewpoint.aspect);
  1161.             display_init(gViewpoint.resx, gViewpoint.resy, gBkgnd_color);
  1162.             gView_init_flag = 1;
  1163.         }
  1164.         /* Step through each segment of the polygon, projecting it
  1165.             onto the screen. */
  1166.         for (i=0;i<tot_vert;i++) {
  1167.             COPY_COORD3(tvert[0], vert[i]);
  1168.             tvert[0][W] = 1.0;
  1169.             lib_transform_coord(v0, tvert[0], gViewpoint.tx);
  1170.             COPY_COORD3(tvert[1], vert[(i+1)%tot_vert]);
  1171.             tvert[1][W] = 1.0;
  1172.             lib_transform_coord(v1, tvert[1], gViewpoint.tx);
  1173.             /* Do the perspective transform on the points */
  1174.             v0[X] /= v0[W]; v0[Y] /= v0[W];
  1175.             v1[X] /= v1[W]; v1[Y] /= v1[W];
  1176.             if (lib_clip_to_box(v0, v1, gView_bounds))
  1177.             display_line((int)v0[X], (int)v0[Y],
  1178.                 (int)v1[X], (int)v1[Y], gFgnd_color);
  1179.         }
  1180.         break;
  1181.  
  1182.         case OUTPUT_NFF:
  1183.         fprintf(gOutfile, "p %d\n", tot_vert);
  1184.         for (num_vert=0;num_vert<tot_vert;++num_vert)
  1185.             fprintf(gOutfile, "%g %g %g\n",
  1186.                 vert[num_vert][X],
  1187.                 vert[num_vert][Y],
  1188.                 vert[num_vert][Z]);
  1189.         break;
  1190.  
  1191.         case OUTPUT_OBJ:
  1192.         /* First the vertices */
  1193.         for (num_vert=0;num_vert<tot_vert;++num_vert)
  1194.             fprintf(gOutfile, "v %g %g %g\n",
  1195.                 vert[num_vert][X],
  1196.                 vert[num_vert][Y],
  1197.                 vert[num_vert][Z]);
  1198.         /* Then the face - note that we add one to the count
  1199.            since Wavefront vertices start at 1, not 0. */
  1200.         fprintf(gOutfile, "f ");
  1201.         for (num_vert=0;num_vert<tot_vert;num_vert++) {
  1202.            fprintf(gOutfile, "%d", gVertex_count+num_vert+1);
  1203.            if (num_vert < tot_vert - 1)
  1204.               fprintf(gOutfile, " ");
  1205.            }
  1206.         fprintf(gOutfile, "\n");
  1207.         gVertex_count += tot_vert;
  1208.         break;
  1209.  
  1210.         case OUTPUT_RWX:
  1211.         /* First the vertices */
  1212.         for (num_vert=0;num_vert<tot_vert;++num_vert) {
  1213.            tab_indent();
  1214.            fprintf(gOutfile, "Vertex %g %g %g\n",
  1215.                vert[num_vert][X],
  1216.                vert[num_vert][Y],
  1217.                vert[num_vert][Z]);
  1218.            }
  1219.         /* Then the face - note that we add one to the count
  1220.            since RenderWare vertices start at 1, not 0. */
  1221.         tab_indent();
  1222.         fprintf(gOutfile, "Polygon %d ", num_vert);
  1223.         for (num_vert=0;num_vert<tot_vert;num_vert++) {
  1224.            fprintf(gOutfile, "%ld", (long)(gVertex_count+num_vert+1));
  1225.            if (num_vert < tot_vert - 1)
  1226.               fprintf(gOutfile, " ");
  1227.            }
  1228.         fprintf(gOutfile, "\n");
  1229.         gVertex_count += tot_vert;
  1230.         break;
  1231.  
  1232.         case OUTPUT_POVRAY_10:
  1233.         case OUTPUT_POVRAY_20:
  1234.         case OUTPUT_QRT:
  1235.         case OUTPUT_PLG:
  1236.         case OUTPUT_RAWTRI:
  1237.         case OUTPUT_DXF:
  1238.         /*
  1239.         These renderers don't do arbitrary polygons, split the polygon
  1240.         into triangles for output
  1241.         */
  1242.         split_polygon(tot_vert, vert, (COORD3 *)NULL);
  1243.         break;
  1244.  
  1245.         case OUTPUT_POLYRAY:
  1246.         tab_indent();
  1247.         fprintf(gOutfile, "object { polygon %d,", tot_vert);
  1248.         for (num_vert = 0; num_vert < tot_vert; num_vert++) {
  1249.             fprintf(gOutfile, " <%g, %g, %g>",
  1250.                  vert[num_vert][X],
  1251.                  vert[num_vert][Y],
  1252.                  vert[num_vert][Z]);
  1253.             if (num_vert < tot_vert-1)
  1254.             fprintf(gOutfile, ", ");
  1255.         }
  1256.         if (gTexture_name != NULL)
  1257.             fprintf(gOutfile, " %s", gTexture_name);
  1258.         fprintf(gOutfile, " }\n");
  1259.         fprintf(gOutfile, "\n");
  1260.         break;
  1261.  
  1262.         case OUTPUT_VIVID:
  1263.         tab_indent();
  1264.         fprintf(gOutfile, "polygon { points %d ", tot_vert);
  1265.         for (num_vert = 0; num_vert < tot_vert; num_vert++) {
  1266.             /* Vivid has problems with very long input lines, so in
  1267.              * order to handle polygons with many vertices, we split
  1268.              * the vertices one to a line.
  1269.              */
  1270.             fprintf(gOutfile, " vertex %g %g %g \n",
  1271.                  vert[num_vert][X],
  1272.                  vert[num_vert][Y],
  1273.                  vert[num_vert][Z]);
  1274.         }
  1275.         fprintf(gOutfile, " }\n");
  1276.         fprintf(gOutfile, "\n");
  1277.         break;
  1278.  
  1279.         case OUTPUT_RAYSHADE:
  1280.         fprintf(gOutfile, "polygon ");
  1281.         if (gTexture_name != NULL)
  1282.             fprintf(gOutfile, "%s ", gTexture_name);
  1283.         for (num_vert=0;num_vert<tot_vert;num_vert++) {
  1284.             if (!(num_vert%3)) fprintf(gOutfile, "\n");
  1285.             fprintf(gOutfile, "%g %g %g ",
  1286.                 vert[num_vert][X],
  1287.                 vert[num_vert][Y],
  1288.                 vert[num_vert][Z]);
  1289.         }
  1290.         fprintf(gOutfile, "\n");
  1291.         break;
  1292.  
  1293.         case OUTPUT_RTRACE:
  1294.         fprintf(gOutfile, "5 %d %g 0 0 0 1 1 1 -\n",
  1295.               gTexture_count, gTexture_ior);
  1296.         fprintf(gOutfile, "%d ", tot_vert);
  1297.         for (num_vert=0;num_vert<tot_vert;num_vert++)
  1298.             fprintf(gOutfile, "%d ", num_vert+1);
  1299.         fprintf(gOutfile, "\n\n");
  1300.         for (num_vert=0;num_vert<tot_vert;num_vert++) {
  1301.             fprintf(gOutfile, "%g %g %g\n",
  1302.                 vert[num_vert][X],
  1303.                 vert[num_vert][Y],
  1304.                 vert[num_vert][Z]);
  1305.         }
  1306.         fprintf(gOutfile, "\n");
  1307.         break;
  1308.  
  1309.         case OUTPUT_ART:
  1310.         tab_indent();
  1311.         fprintf(gOutfile, "polygon {\n");
  1312.         tab_inc();
  1313.  
  1314.         for (num_vert=0;num_vert<tot_vert;num_vert++) {
  1315.             tab_indent();
  1316.             fprintf(gOutfile, "vertex(%f, %f, %f)\n",
  1317.                   vert[num_vert][X],
  1318.                   vert[num_vert][Y],
  1319.                   vert[num_vert][Z]);
  1320.         }
  1321.         tab_dec();
  1322.         tab_indent();
  1323.         fprintf(gOutfile, "}\n");
  1324.         fprintf(gOutfile, "\n");
  1325.         break;
  1326.  
  1327.         case OUTPUT_RIB:
  1328.         tab_indent();
  1329.         fprintf(gOutfile, "Polygon \"P\" [\n");
  1330.         tab_inc();
  1331.  
  1332.         for (num_vert=tot_vert-1;num_vert>=0;num_vert--)
  1333.         {
  1334.             tab_indent();
  1335.             fprintf(gOutfile, "%#g %#g %#g\n",
  1336.                 vert[num_vert][X], vert[num_vert][Y],
  1337.                 vert[num_vert][Z]);
  1338.         }
  1339.  
  1340.         tab_dec();
  1341.         tab_indent();
  1342.         fprintf(gOutfile, "]\n");
  1343.         break;
  1344.  
  1345.      } /* switch */
  1346.     } /* else !OUTPUT_DELAYED */
  1347. }
  1348.  
  1349.  
  1350. /*-----------------------------------------------------------------*/
  1351. /*
  1352.  * Output polygonal patch.  A patch is defined by a set of vertices and their
  1353.  * normals.  With these databases, a patch is defined to have all points
  1354.  * coplanar.  A patch has only one side, with the order of the vertices being
  1355.  * counterclockwise as you face the patch (right-handed coordinate system).
  1356.  *
  1357.  * The output format is always:
  1358.  *   "pp" total_vertices
  1359.  *   vert1.x vert1.y vert1.z norm1.x norm1.y norm1.z
  1360.  *   [etc. for total_vertices polygonal patches]
  1361.  *
  1362.  */
  1363. void
  1364. lib_output_polypatch(tot_vert, vert, norm)
  1365.     int tot_vert;
  1366.     COORD3 vert[], norm[];
  1367. {
  1368.     /* None of the currently supported renderers are capable of directly
  1369.        generating polygon patches of more than 3 sides.   Therefore we
  1370.        will call a routine to split the patch into triangles.
  1371.     */
  1372.     split_polygon(tot_vert, vert, norm);
  1373. }
  1374.